﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameEngine;

namespace Daphne.Presenters
{
    public class ProfessionalGameBoardPresenter: IProfessionalGameBoardView
    {
        #region Constants for drawing the board

        private const double m_startX = 70;
        private const double m_startY = 70;
        private const double m_endX = 950;
        private const double m_endY = 950;
        private double m_numFields;
        private double m_fieldSize;
        private const double m_startX10 = 32;
        private const double m_startY10 = 33;
        private const double m_endX10 = 567;
        private const double m_endY10 = 568;

        private const int m_FigureImageWidth = 60;
        private const int m_FigureImageHeight = 60;
        private const int m_BoardImageWidth = 1024;
        private const int m_BoardImageHeight = 1024;

        private const double crossMargin = 10;
        private const double crossWidth = 6;

        #endregion

        #region Private attributes

        private Position m_SelectedFigure;
        private Position m_LastMouseMovePos;
        private List<Position> m_FieldsToMove;
        private Move m_MoveToDo;
        private bool _inEditMode = false;

        private enumDrawnImage? _imageToAnimate;
        private double _animationX = 0;
        private double _animationY = 0;

        private enumDrawnImage? _imageOpacity = null;
        private TGameBoardDrawRect _rectOpacityImage;
        private int _opacityAlpha = 0;

        private byte _FlashAlpha;
        private List<Position> _flashPositions = new List<Position>();
        private List<Position> ignoreFigureFields = new List<Position>();

        protected Position _posDragFigure;
        protected TGameBoardPoint? _pointDragPoint;
        protected Position _posDropField;

        private bool _blockedInput = false;

        private Move _shownMove = null;


        #endregion


        public ProfessionalGameBoardPresenter()
        {
            m_SelectedFigure = Position.Empty;
            m_FieldsToMove = new List<Position>();
            m_LastMouseMovePos = Position.Empty;
            m_MoveToDo = null;
            _pointDragPoint = null;
			_posDragFigure = Position.Empty;

            this.Rotated = false;
            this.ShowNumberCoordinates = true;
        }

        #region Public Interface

        /// <summary>
        /// Event fired when a move is done by the user
        /// </summary>
        public event TMoveDoneDelegate MoveDoneEvent;

        /// <summary>
        /// True, if board rotated upside down
        /// </summary>
        public bool Rotated
        { get; set; }

        /// <summary>
        /// True, if checkers number coordinates are displayed
        /// </summary>
        public bool ShowNumberCoordinates
        { get; set; }

        /// <summary>
        /// Move to show
        /// </summary>
        public Move MoveToShow
        {
            get
            {
                return _shownMove;
            }
            set
            {
                _shownMove = value;
            }
        }

        /// <summary>
        /// Set by creator class, reference to the game manager for the evaluation of moves
        /// </summary>
        public GameManager GameManager
        { get; set;  }

        /// <summary>
        /// Event signalled when a figure is placed in edit mode
        /// </summary>
        public event EventHandler<FigurePlacedArgs> FigurePlacedEvent;



        /// <summary>
        /// Starts or exists edit mode
        /// </summary>
        public void ToggleEditMode()
        {
            _inEditMode = ! _inEditMode;

            m_SelectedFigure = Position.Empty;
            m_FieldsToMove.Clear();
            m_LastMouseMovePos = Position.Empty;
        }

        /// <summary>
        /// Returns status if we are in edit mode
        /// </summary>
        public bool IsInEditMode()
        {
            return _inEditMode;
        }

        public void BlockInput()
        {
            _blockedInput = true;
        }

        public void UnblockInput()
        {
            _blockedInput = false;
        }

        #endregion

        #region IView Interface

        public event TStartDraw StartDrawEvent;
        public event TEndDraw EndDrawEvent;
        public event TDrawText DrawTextEvent;
        public event TDrawImage DrawImageEvent;
        public event TDrawFilledRectangle DrawFilledRectangleEvent;
        public event TControlRedraw ControlRedrawEvent;
        public event TSetCapture SetCaptureEvent;
        public event TReleaseCapture ReleaseCaptureEvent;
        public event TStartTimer StartTimerEvent;
        public event TStopTimer StopTimerEvent;



        /// <summary>
        /// Handles left button down event
        /// </summary>
        public void LeftButtonDown (double x, double y)
        {
            if (_blockedInput == true)
                return;

            if (_inEditMode == true)
                return;

            Position pos;
            GetFieldByPoint(new TGameBoardPoint(x, y), out pos);

            if (pos.Row == -1 || pos.Col == -1)
                return;
            if (pos.Row >= GameManager.GameBoard.Size || pos.Col >= GameManager.GameBoard.Size)
                return;

            if (GameManager.GameBoard.GetField(pos) == enumFigureType.Nothing)
                return;
            if (GameManager.GameBoard.GetField(pos).FigureColor() != GameManager.GameBoard.OnMove)
                return;

            List<Position> dummy = new List<Position>(); ;
            GameManager.GetFigureMoves(pos, dummy);
            if (dummy.Count > 0)
            {
                _posDragFigure = pos;
                _pointDragPoint = new TGameBoardPoint(x, y);
                if (SetCaptureEvent != null)
                    SetCaptureEvent();
                if (ControlRedrawEvent != null)
                {
                    ControlRedrawEvent();
                }                   
            }
        }

        /// <summary>
        /// Handles left button click
        /// </summary>
        public void LeftButtonUp (double x, double y)
		{
            if (_blockedInput == true)
                return;

			Position pos;
			GetFieldByPoint (new TGameBoardPoint (x, y), out pos);

            if (pos.Row == -1 || pos.Col == -1)
                return;
            if (pos.Row >= GameManager.GameBoard.Size || pos.Col >= GameManager.GameBoard.Size)
                return;

			if (pos.IsEmpty () == false) {
				if (_inEditMode == true) {
					if (GameManager.GameBoard.GetFieldColor (pos.Row, pos.Col) == enumFigureColor.Black) {
						enumFigureType figureType = EditorGetNextFigure (pos, true);
                       
                        // added event for signalling the event that figure has been placed
                        BitBoard bb = GameManager.GameBoard.PackGameBoard();
                        if (FigurePlacedEvent != null)
                        {
                            FigurePlacedArgs args = new FigurePlacedArgs();
                            args.SavedPosition = bb;
                            FigurePlacedEvent(this, args);
                        }

                        GameManager.GameBoard.PlaceFigure(pos, figureType);
					}
				} else {
					Position startPos = _posDragFigure;
					Position endPos = _posDropField;

					_pointDragPoint = null;
					_posDragFigure = Position.Empty;
					_posDropField = Position.Empty;
					if (ReleaseCaptureEvent != null)
						ReleaseCaptureEvent ();

					if (startPos != Position.Empty && endPos != Position.Empty) {
						if (GameManager.CanFigureMoveHere (startPos, endPos) == true) {
							Move move = GameManager.CompleteMoveStep (startPos, endPos);
							GameManager.DoMoveStep (move);
							AddMove (move);
							if (GameManager.DoesMoveContinue (move, endPos) == false) {
								CallMoveDoneEvent ();
							}
                        }
                    }
                }

                if (ControlRedrawEvent != null)
                {
                    ControlRedrawEvent();
                }
            }

        }

        
        /// <summary>
        /// Handles right button click
        /// </summary>
        public void RightButtonUp (double x, double y)        
        {
            if (_blockedInput == true)
                return;

            Position pos;
            GetFieldByPoint(new TGameBoardPoint(x, y), out pos);

            if (pos.Row == -1 || pos.Col == -1)
                return;
            if (pos.Row >= GameManager.GameBoard.Size || pos.Col >= GameManager.GameBoard.Size)
                return;

            if (pos.IsEmpty() == false)
            {
                if (_inEditMode == true)
                {
                    if (GameManager.GameBoard.GetFieldColor(pos.Row, pos.Col) == enumFigureColor.Black)
                    {
                        if (GameManager.GameBoard.GetFieldColor(pos.Row, pos.Col) == enumFigureColor.Black)
                        {
                            enumFigureType figureType = EditorGetNextFigure(pos, false);

                            // added event for signalling the event that figure has been placed
                            BitBoard bb = GameManager.GameBoard.PackGameBoard();
                            if (FigurePlacedEvent != null)
                            {
                                FigurePlacedArgs args = new FigurePlacedArgs();
                                args.SavedPosition = bb;
                                FigurePlacedEvent(this, args);
                            }

                            GameManager.GameBoard.PlaceFigure(pos, figureType);
                        }
                    }
                }

                if (ControlRedrawEvent != null)
                {
                    ControlRedrawEvent();
                }
            }
        }

        public void MouseMove (double x, double y)
		{
            if (_blockedInput == true)
                return;

			m_FieldsToMove.Clear ();
			
			if (_inEditMode == true)            
				return;
		
			double mouseX = x;			
			double mouseY = y;

            Position pos;
            GetFieldByPoint(new TGameBoardPoint(mouseX, mouseY), out pos);

            if (pos.Row == -1 || pos.Col == -1)
                return;
            if (pos.Row >= GameManager.GameBoard.Size || pos.Col >= GameManager.GameBoard.Size)
                return;
			
			if (_posDragFigure == Position.Empty) {
				if (pos.IsEmpty () == false)
				{				
					enumFigureType figureType = GameManager.GameBoard.GetField (pos);
					if (figureType != enumFigureType.Nothing
					    && figureType.FigureColor () == GameManager.GameBoard.OnMove)
					{					
						List<Position> posList = new List<Position> ();
						GameManager.GetFigureMoves (pos, posList);
						m_FieldsToMove.AddRange (posList);
					}
				}
			} else {
				enumFigureType figureType = GameManager.GameBoard.GetField (_posDragFigure);
				if (figureType != enumFigureType.Nothing)
				{
                    //x = mouseX - m_FigureImageWidth / 2;
                    //y = mouseY - m_FigureImageHeight / 2;
                    x = mouseX;
                    y = mouseY;
		
					if (x < 0)
						x = 0;
					if (y < 0)
						y = 0;
					if (x + m_FigureImageWidth > m_BoardImageWidth)
						x = m_BoardImageWidth - m_FigureImageWidth;
					if (y + m_FigureImageHeight > m_BoardImageHeight)
						y = m_BoardImageHeight - m_FigureImageHeight;
		
					_pointDragPoint = new TGameBoardPoint (x, y);
		
					_posDropField = Position.Empty;
					GetFieldByPoint (new TGameBoardPoint (mouseX, mouseY), out pos);
					if (pos.Row != -1 && pos.Col != -1) {
						if (GameManager.CanFigureMoveHere (_posDragFigure, pos) == true) {
							_posDropField = pos;
						}						
					}
				}
			}
			
			if (ControlRedrawEvent != null)
				ControlRedrawEvent ();								
			
        }

        /// <summary>
        /// Public method to draw the board
        /// </summary>
        public void DrawBoard()
        {
            RenderGameBoard();
        }

        #endregion

        #region Animations

        private const int iSleep = 10;
        private const int iMaxAlpha = 100;
        private const int iAlphaIncr = 8;
        private int _flashStep;

        private void FlashFieldsTick()
        {
            if (_flashStep == 0)
            {
                if (ControlRedrawEvent != null)
                {
                    ControlRedrawEvent();
                }

                _FlashAlpha += iAlphaIncr;

                if (_FlashAlpha >= iMaxAlpha)
                    _flashStep++;
            }
            else if (_flashStep == 1)
            {
                if (_FlashAlpha < iAlphaIncr)
                    _FlashAlpha = 0;
                else
                    _FlashAlpha -= iAlphaIncr;

                if (ControlRedrawEvent != null)
                {
                    ControlRedrawEvent();
                }

                if (_FlashAlpha <= 0)
                {
                    StopTimerEvent();
                }

                _flashPositions.Clear();
            }
        }

        public void FlashFields(List<Position> flashFields)
        {
            _flashPositions.Clear();
            _flashPositions.AddRange(flashFields);
            _FlashAlpha = 0;
            _flashStep = 0;

            StartTimerEvent(iSleep, this.FlashFieldsTick);
        }

        public void AnimateMove(Move move)
        {
            ignoreFigureFields.Add(move.startPos);

            _imageToAnimate = GetImageForFigure(GameManager.GameBoard.GetField(move.startPos));

            DoMoveStepAnimation(move);
        }

        private const int framesPerField = 20;
        private const int waitingPerFrame = 10;
        private const int opacityStep = 15;
        private const int opacityWaiting = 15;
        private TGameBoardDrawRect fieldRectStart, fieldRectEnd;
        private TGameBoardDrawRect imageRectStart, imageRectEnd;
        private double offsetX;
        private double offsetY;
        private int _animFrame;
        int framesPerMoveStep;
        private Move _animatedMove;

        public event EventHandler AnimationMoveFinishedEvent;

        private void FigureDeleteTick()
        {
            _opacityAlpha -= opacityStep;
            if(_opacityAlpha <= 0)
            {
                StopTimerEvent();

                _imageOpacity = null;

                if (_animatedMove.nextMove != null)
                {
                    DoMoveStepAnimation(_animatedMove.nextMove);
                    return;
                }

                AnimationMoveFinishedEvent(this, EventArgs.Empty);
                _imageToAnimate = null;
                ignoreFigureFields.Clear();

                this.UnblockInput();
            }

            if (ControlRedrawEvent != null)
            {
                ControlRedrawEvent();
            }
        }


        private void AnimateMoveTick()
        {
            if (ControlRedrawEvent != null)
            {
                ControlRedrawEvent();
            }

            _animationX += offsetX;
            _animationY += offsetY;

            _animFrame++;

            if (_animFrame >= framesPerMoveStep)
            {
                StopTimerEvent();

                if (_animatedMove.RemovingFigure == true && _animatedMove.removedFigurePlace != Position.Empty
                    && _animatedMove.removedFigure != enumFigureType.Nothing)
                {
                    _imageOpacity = GetImageForFigure(_animatedMove.removedFigure);
                    ignoreFigureFields.Add(_animatedMove.removedFigurePlace);

                    TGameBoardDrawRect fieldRect;
                    GetFieldRect(_animatedMove.removedFigurePlace, out fieldRect);
                    _rectOpacityImage = CalculateRectForFigureImage(fieldRect);

                    _opacityAlpha = 255;
                    StartTimerEvent(opacityWaiting / 2 , FigureDeleteTick);
                    return;
                }


                if (_animatedMove.nextMove != null)
                {
                    DoMoveStepAnimation(_animatedMove.nextMove);
                    return;
                }


                AnimationMoveFinishedEvent(this, EventArgs.Empty);
                _imageToAnimate = null;
                ignoreFigureFields.Clear();

                this.UnblockInput();
            }
        }
        

        private void DoMoveStepAnimation (Move move)
		{
            _animFrame = 0;
			int numFields = Math.Abs (move.endPos.Row - move.startPos.Row);
			framesPerMoveStep = framesPerField * numFields;

			GetFieldRect (move.startPos, out fieldRectStart);
			GetFieldRect (move.endPos, out fieldRectEnd);

			imageRectStart = CalculateRectForFigureImage (fieldRectStart);
			imageRectEnd = CalculateRectForFigureImage (fieldRectEnd);

			offsetX = (imageRectEnd.X - imageRectStart.X) / (double)framesPerMoveStep;
			offsetY = (imageRectEnd.Y - imageRectStart.Y) / (double)framesPerMoveStep;

            _animationX = imageRectStart.X;
            _animationY = imageRectStart.Y;
            _animatedMove = move;

            this.BlockInput();

            StartTimerEvent(waitingPerFrame, AnimateMoveTick);

        }

        #endregion

        #region Drawing methods

        /// <summary>
        /// The main rendering method
        /// </summary>
        protected void RenderGameBoard()
        {
            if (StartDrawEvent != null)
                StartDrawEvent();

            DrawBoardWithFigures();
            DrawFieldsToMove();
            MarkFigureToMove();
            if (this.ShowNumberCoordinates == true)
                DrawNumberNotation();

            DrawMoveToShow();

            DrawAnimatedFigure();
            DrawOpacityImage();

            DrawDraggedFigure();

            if (EndDrawEvent != null)
                EndDrawEvent();
        }


        /// <summary>
        /// Draws checkers coordinates
        /// </summary>
        protected void DrawNumberNotation()
        {
            for (int row = 0; row < GameManager.GameBoard.Size; row++)
                for (int col = 0; col < GameManager.GameBoard.Size; col++)
                {
                    if (GameManager.GameBoard.GetFieldColor(row, col) == enumFigureColor.Black)
                    {
                        Position pos = new Position(row, col);
                        string notation = GameManager.ToNumberNotation(pos);
                        TGameBoardDrawRect rect;
                        GetFieldRect(pos, out rect);

                        if (DrawTextEvent != null)
                        {
                            DrawTextEvent(rect.X, rect.Y, notation, "FFFF00");
                        }
                    }
                }
        }

        /// <summary>
        /// Renders gameboard with figures
        /// </summary>
        protected void DrawBoardWithFigures ()
		{
			// draw the board
			DrawGameBoard ();

			// can be run by visual studio preview
			if (GameManager == null)
				return;

			// draw figures
            for (int row = 0; row < GameManager.GameBoard.Size; row++)
                for (int col = 0; col < GameManager.GameBoard.Size; col++)
                {
				
					enumFigureType figureType = GameManager.GameBoard.GetField (row, col);
					if (figureType != enumFigureType.Nothing) {
						Position pos = new Position (row, col);
						if (IsFieldOnIgnoredList (pos) == true)
							continue;
						if (pos == _posDragFigure)
							continue;

                        TGameBoardDrawRect fieldRect;
                        GetFieldRect(pos, out fieldRect);

                        TGameBoardDrawRect drawRect = CalculateRectForFigureImage(fieldRect);

                        enumDrawnImage drawImage = GetImageForFigure(figureType);

                        if (DrawImageEvent != null)
                        {
                            DrawImageEvent(drawRect, drawImage, 255);
                        }


                        DrawFlashingFigure(pos);
                    } // if
                } // for
        }

        protected void DrawMoveToShow()
        {
            if (_shownMove == null)
                return;

            // draw starting position - hover over figure image
            string sFigColor = "ff0000";
            int figAlpha = 128;

            TGameBoardDrawRect fieldRect;
            GetFieldRect(_shownMove.startPos, out fieldRect);

            TGameBoardDrawRect markRect = new TGameBoardDrawRect(fieldRect.X, fieldRect.Y, fieldRect.Width, fieldRect.Height);
            if (DrawFilledRectangleEvent != null)
            {
                DrawFilledRectangleEvent(markRect, sFigColor, figAlpha, 2);
            }

            // draw destination fields
            Move tmpMove = _shownMove;
            while (tmpMove != null)
            {
                Position pos = tmpMove.endPos;

                string sMarkColor = "B0B000";
                int alpha = 192;

                GetFieldRect(pos, out fieldRect);

                double rel = fieldRect.Width / 4;
                markRect = new TGameBoardDrawRect(fieldRect.X + rel, fieldRect.Y + rel, rel * 2, rel * 2);
                if (DrawFilledRectangleEvent != null)
                {
                    DrawFilledRectangleEvent(markRect, sMarkColor, alpha, 2);
                }

                tmpMove = tmpMove.nextMove;
            }
        }

        protected TGameBoardDrawRect CalculateRectForFigureImage (TGameBoardDrawRect fieldRect)
		{
            const int margin = 3;
            double imageWidth = m_FigureImageWidth;
            double imageHeight = m_FigureImageHeight;
            //if (imageWidth > fieldRect.Width)
                imageWidth = fieldRect.Width - margin * 2;
            //if (imageHeight > fieldRect.Height)
                imageHeight = fieldRect.Height - margin * 2;

			double spaceX = (fieldRect.Width - imageWidth) / 2;
			double spaceY = (fieldRect.Height - imageHeight) / 2;
            return new TGameBoardDrawRect(fieldRect.X + spaceX, fieldRect.Y + spaceY,
                                    imageWidth, imageHeight);
        }


        /// <summary>
        /// Returns true, if figure on this positon should not be painted
        /// </summary>
        private bool IsFieldOnIgnoredList(Position pos)
        {
            foreach (Position p in ignoreFigureFields)
            {
                if (p == pos)
                    return true;
            } // foreach

            return false;
        }

        /// <summary>
        /// Returns drawn image for specific figure
        /// </summary>
        private enumDrawnImage GetImageForFigure(enumFigureType figureType)
        {
            enumDrawnImage drawImage;

            switch (figureType)
            {
                case enumFigureType.WhiteMan:
                    drawImage = enumDrawnImage.WhiteMan;
                    break;
                case enumFigureType.BlackMan:
                    drawImage = enumDrawnImage.BlackMan;
                    break;
                case enumFigureType.WhiteKing:
                    drawImage = enumDrawnImage.WhiteKing;
                    break;
                default:
                    drawImage = enumDrawnImage.BlackKing;
                    break;
            }

            return drawImage;
        }

        /// <summary>
        /// Paints the game board itself
        /// </summary>
        protected void DrawGameBoard()
        {
            TGameBoardDrawRect rect = new TGameBoardDrawRect(0, 0, m_BoardImageWidth, m_BoardImageHeight);
            enumDrawnImage drawImage = enumDrawnImage.Board;

            if (this.Rotated == true)
                drawImage = enumDrawnImage.BoardRotated;
            if (GameManager.GameBoard.Size == 10)
                drawImage = enumDrawnImage.Board10;

            if (DrawImageEvent != null)
            {
                DrawImageEvent(rect, drawImage, 255);
            }


            if(_inEditMode == true)
            {
                DrawCrosses();
            }
        }

        protected void DrawCrosses()
        {
            if (DrawFilledRectangleEvent == null)
                return;

            for (int row = 0; row < GameManager.GameBoard.Size; row++)
                for (int col = 0; col < GameManager.GameBoard.Size; col++)
                {
                    if (GameManager.GameBoard.GetFieldColor(row, col) == enumFigureColor.Black)
                    {
                        TGameBoardDrawRect fieldRect;
                        GetFieldRect(new Position(row, col), out fieldRect);

                        TGameBoardDrawRect drawRect;
                        double middleX = fieldRect.X + fieldRect.Width / 2;
                        double middleY = fieldRect.Y + fieldRect.Height / 2;

                        drawRect.X = fieldRect.X + crossMargin;
                        drawRect.Y = middleY - crossWidth / 2;
                        drawRect.Width = fieldRect.Width - 2 * crossMargin;
                        drawRect.Height = crossWidth;

                        DrawFilledRectangleEvent(drawRect, "ff9900", 200, 5);

                        drawRect.X = middleX - crossWidth / 2;
                        drawRect.Y = fieldRect.Y + crossMargin;
                        drawRect.Width = crossWidth;
                        drawRect.Height = fieldRect.Height - 2 * crossMargin;

                        DrawFilledRectangleEvent(drawRect, "ff9900", 200, 5);
                    }
                }
        }

        /// <summary>
        /// Draw fields to move
        /// </summary>
        protected void DrawFieldsToMove ()
		{
			string sMarkColor = "B0B000";
			int alpha = 192;

			foreach (Position pos in m_FieldsToMove) {
				TGameBoardDrawRect fieldRect;
				GetFieldRect (pos, out fieldRect);

				double rel = fieldRect.Width / 4;
                TGameBoardDrawRect markRect = new TGameBoardDrawRect(fieldRect.X + rel, fieldRect.Y + rel, rel * 2, rel * 2);
                if (DrawFilledRectangleEvent != null)
                {
                    DrawFilledRectangleEvent(markRect, sMarkColor, alpha, 2);
                }
            }
        }       
        
        /// <summary>
        /// Draws the flashing figure
        /// </summary>
        protected void DrawFlashingFigure(Position pos)
        {
            string  sFlashColor = "FF0000";

            if (_flashPositions.Contains(pos) == true)
            {
                TGameBoardDrawRect fieldRect;
                GetFieldRect(pos, out fieldRect);

                if (DrawFilledRectangleEvent != null)
                {
                    DrawFilledRectangleEvent(fieldRect, sFlashColor, _FlashAlpha, 0);
                }
            }
        }

        /// <summary>
        /// Colors the figure to draw
        /// </summary>
        protected void MarkFigureToMove()
        {
            if (m_SelectedFigure == Position.Empty)
                return;
            TGameBoardDrawRect fieldRect;
            GetFieldRect(m_SelectedFigure, out fieldRect);

            string sColor = "008000";
            int alpha = 128;
            if (DrawFilledRectangleEvent != null)
            {
                DrawFilledRectangleEvent(fieldRect, sColor, alpha, 0);
            }
        }

        /// <summary>
        /// Draws animated figure
        /// </summary>
        protected void DrawAnimatedFigure()
        {
            if (_imageToAnimate != null)
            {
                TGameBoardDrawRect fieldRect;
                GetFieldRect(new Position(0,0), out fieldRect);
                TGameBoardDrawRect drawRect = CalculateRectForFigureImage(fieldRect);

                TGameBoardDrawRect rect = new TGameBoardDrawRect(_animationX, _animationY,
                            drawRect.Width, drawRect.Height);

                if (DrawImageEvent != null)
                {
                    DrawImageEvent(rect, _imageToAnimate.Value, 255);
                }
            }
        }

        protected void DrawDraggedFigure()
        {
            if (_pointDragPoint.HasValue)
            {
                TGameBoardDrawRect fieldRect;
                GetFieldRect(new Position(0, 0), out fieldRect);
                TGameBoardDrawRect drawRect = CalculateRectForFigureImage(fieldRect);

                double halfWidth = drawRect.Width / 2;
                double halfHeight = drawRect.Height / 2;               

                TGameBoardDrawRect rect = new TGameBoardDrawRect(_pointDragPoint.Value.X - halfWidth, _pointDragPoint.Value.Y - halfHeight,
                            drawRect.Width, drawRect.Height);
                enumFigureType figureType = GameManager.GameBoard.GetField(_posDragFigure);
                if (figureType == enumFigureType.Nothing)
                    return;
                enumDrawnImage drawnImage = GetImageForFigure(figureType);

                if (DrawImageEvent != null)
                {
                    DrawImageEvent(rect, drawnImage,255);
                }
            }
        }

        /// <summary>
        /// Draws image with alpha color
        /// </summary>
        protected void DrawOpacityImage()
        {
            if (_imageOpacity != null)
            {
                if (DrawImageEvent != null)
                {
                    DrawImageEvent(_rectOpacityImage, _imageOpacity.Value, _opacityAlpha);
                }
            }
        }

        #endregion

        #region Other private methods

        /// <summary>
        /// Fires the move-done event 
        /// </summary>
        private void CallMoveDoneEvent()
        {
            if (MoveDoneEvent != null)
            {
                MoveDoneEvent(m_MoveToDo);
            }

            m_MoveToDo = null;
        }

        /// <summary>
        /// Adds another following move in the multiple jump
        /// </summary>
        protected void AddMove(Move move)
        {
            if (m_MoveToDo == null)
            {
                m_MoveToDo = move;
                return;
            }
            Move lastMove = m_MoveToDo;
            while (lastMove.nextMove != null)
                lastMove = lastMove.nextMove;
            lastMove.nextMove = move;
        }

        /// <summary>
        /// Returns next figure for editor when clicked on the field
        /// </summary>
        private enumFigureType EditorGetNextFigure(Position pos, bool leftButton)
        {
            enumFigureType figureType = GameManager.GameBoard.GetField(pos);

            if (leftButton == true)
            {
                switch (figureType)
                {
                    case enumFigureType.WhiteMan:
                        return enumFigureType.WhiteKing;
                    case enumFigureType.WhiteKing:
                        return enumFigureType.Nothing;
                    default:
                        return enumFigureType.WhiteMan;
                }
            }
            else
            {
                switch (figureType)
                {
                    case enumFigureType.BlackMan:
                        return enumFigureType.BlackKing;
                    case enumFigureType.BlackKing:
                        return enumFigureType.Nothing;
                    default:
                        return enumFigureType.BlackMan;
                }
            }
        }

        #endregion


        #region Helper board metrics methods

        /// <summary>
        /// Converts positon for inverted board if necessary
        /// </summary>
        protected void CheckCoordinatesRotated(ref Position pos)
        {
            if (this.Rotated == true)
            {
                pos.Row = GameManager.GameBoard.Size - 1 - pos.Row;
                pos.Col = GameManager.GameBoard.Size - 1 - pos.Col;
            }
        }

        /// <summary>
        /// Returns rect for drawing for given position
        /// </summary>
        protected void GetFieldRect(Position pos, out TGameBoardDrawRect fieldRect)
        {
            CheckCoordinatesRotated(ref pos);

            m_fieldSize = (m_endX - m_startX) / GameManager.GameBoard.Size;
            if(GameManager.GameBoard.Size == 10)
                m_fieldSize = (m_endX10 - m_startX10) / GameManager.GameBoard.Size;

            // calculate the field
            double fieldX = pos.Col * m_fieldSize + m_startX;
            double fieldY = (GameManager.GameBoard.Size - pos.Row - 1) * m_fieldSize + m_startY;

            if (GameManager.GameBoard.Size == 10)
            {
                fieldX = pos.Col * m_fieldSize + m_startX10;
                fieldY = (GameManager.GameBoard.Size - pos.Row - 1) * m_fieldSize + m_startY10;
            }

            fieldRect = new TGameBoardDrawRect(fieldX, fieldY, m_fieldSize, m_fieldSize);
        }

        /// <summary>
        /// Returns position by given mouse coordinates
        /// </summary>
        protected void GetFieldByPoint(TGameBoardPoint point, out Position pos)
        {
            pos = Position.Empty;

            m_fieldSize = (m_endX - m_startX) / GameManager.GameBoard.Size;
            if (GameManager.GameBoard.Size == 10)
                m_fieldSize = (m_endX10 - m_startX10) / GameManager.GameBoard.Size;

            double x = point.X - m_startX;
            double y = point.Y - m_startY;
            if (GameManager.GameBoard.Size == 10)
            {
                x = point.X - m_startX10;
                y = point.Y - m_startY10;
            }

            if (x < 0 || y < 0)
                return;

            x = x / m_fieldSize;
            y = y / m_fieldSize;

            int col = (int)Math.Floor(x);
            int row = (int)GameManager.GameBoard.Size - (int)Math.Floor(y) - 1;

            if (row >= GameManager.GameBoard.Size|| col >= GameManager.GameBoard.Size)
                return;

            pos = new Position(row, col);
            CheckCoordinatesRotated(ref pos);
        }

        #endregion
    }
}
